home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 27 / CU Amiga Magazine's Super CD-ROM 27 (1998)(EMAP Images)(GB)[!][issue 1998-10].iso / CUCD / Magazine / C_Tutorial / Part-15 / hook0.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-04  |  8.1 KB  |  335 lines

  1. #include<dos/dos.h>
  2. #include<dos/exall.h>
  3. #include<exec/libraries.h>
  4. #include<exec/memory.h>
  5. #include<exec/nodes.h>
  6. #include<graphics/text.h>
  7. #include<intuition/intuition.h>
  8. #include<intuition/screens.h>
  9. #include<libraries/gadtools.h>
  10. #include<utility/tagitem.h>
  11.  
  12. #include<string.h>
  13. #include<stdio.h>
  14. #include<stdlib.h>
  15.  
  16. #include<clib/alib_protos.h>
  17. #include<clib/dos_protos.h>
  18. #include<clib/exec_protos.h>
  19. #include<clib/gadtools_protos.h>
  20. #include<clib/intuition_protos.h>
  21.  
  22. /* The library base global variables */
  23. struct Library* DosBase;
  24. struct Library* GadToolsBase;
  25. struct Library* IntuitionBase;
  26.  
  27. /* Need to give prototypes for our functions */
  28. void handleIDCMP(struct Window*);
  29. void setupWindow(void);
  30. void createWindow(struct Gadget*);
  31.  
  32. void addNode(char*,int);
  33. void freeNode(struct Node*);
  34. void freeList(void);
  35. int  fillList(char*);
  36. void sortList(void);
  37.  
  38. #define MYFONTSIZE        (8)
  39.  
  40. /* Some constants for the size of the window */
  41. #define MYWIN_WIDTH        (200)
  42. #define MYWIN_HEIGHT    (200)
  43.  
  44. /* Some constants for the position and size of our gadget */
  45. #define MYGAD_LEFT        (10)
  46. #define MYGAD_TOP            (10+MYFONTSIZE)
  47. #define MYGAD_WIDTH        (MYWIN_WIDTH-MYGAD_LEFT*2)
  48. #define MYGAD_HEIGHT    (MYWIN_HEIGHT-MYGAD_TOP*2+MYFONTSIZE)
  49. #define MYGAD_TEXT        ("Files")
  50. #define MYGAD_ID            (0)
  51.  
  52.  
  53. /* Constants for the Node type, deciding dir or file */
  54.  
  55. #define MY_FILE  (NT_USER)
  56. #define MY_DIR   (NT_USER-1)
  57.  
  58.  
  59. /* Initialised structure declaration: describes standard Topaz font */
  60. static struct TextAttr topazFont = { "topaz.font", MYFONTSIZE, 0, 0, };
  61.  
  62. static struct List mylist;
  63. static int mycount = 0;
  64.  
  65. void addNode(char* name, int isdir)
  66. {
  67.     if(name)
  68.     {
  69.         struct Node* node = AllocVec(sizeof(struct Node), MEMF_PUBLIC | MEMF_CLEAR);
  70.         if(node)
  71.         {
  72.             if(node->ln_Name = AllocVec(strlen(name)+1, MEMF_PUBLIC))
  73.                 strcpy(node->ln_Name, name);
  74.             node->ln_Type = (isdir ? MY_DIR : MY_FILE);
  75.             AddTail(&mylist, node);
  76.             mycount++;
  77.         }
  78.     }
  79. }
  80.  
  81. void freeNode(struct Node* node)
  82. {
  83.     FreeVec(node->ln_Name);
  84.     FreeVec(node);
  85. }
  86.  
  87. void freeList()
  88. {
  89.     struct Node* work;
  90.     struct Node* next = mylist.lh_Head;
  91.     while(next->ln_Succ)
  92.     {
  93.         work = next;
  94.         next = next->ln_Succ;
  95.         freeNode(work);
  96.     }
  97.     mycount = 0;
  98. }
  99.  
  100. #define EABUFF_NUM  (30)
  101. #define EABUFF_SIZE (EABUFF_NUM*sizeof(struct ExAllData))
  102.  
  103. /* Our buffer for ExAll() */
  104. static struct ExAllData EABuff[EABUFF_NUM];
  105.  
  106. int fillList(char* dir)
  107. {
  108.     int success = FALSE;
  109.     /* Get a lock on the directory */
  110.     BPTR lock = Lock(dir, ACCESS_READ);
  111.     if(lock)
  112.     {
  113.         /* Allocate ExAll control object */
  114.         struct ExAllControl* eac = AllocDosObject(DOS_EXALLCONTROL,NULL);
  115.         if(eac)
  116.         {
  117.             int going = TRUE;
  118.             /* Must initialise LastKey to zero before calling ExAll() */
  119.             eac->eac_LastKey = 0;
  120.             /* If we got this far we're OK */
  121.             success = TRUE;
  122.             while(going)
  123.             {
  124.                 /* Fill the buffer with directory entries */
  125.                 /* (We need the type as well as the name, so ED_TYPE) */
  126.                 going = ExAll(lock, EABuff, EABUFF_SIZE, ED_TYPE, eac);
  127.                 /* It's only an error if ExAll() returns FALSE and IoErr() signals */
  128.                 /* something other than running out of directory entries */
  129.                 if(!going)
  130.                     success = (IoErr() == ERROR_NO_MORE_ENTRIES);
  131.                 if(success)
  132.                 {
  133.                     if(eac->eac_Entries != 0)
  134.                     {
  135.                         /* Run through a buffer load of entries */
  136.                         struct ExAllData* ead = EABuff;
  137.                         while(ead)
  138.                         {
  139.                             /* If ed_Type>0 then it's a directory */
  140.                             addNode(ead->ed_Name, ead->ed_Type > 0);
  141.                             ead = ead->ed_Next;
  142.                         }
  143.                     }
  144.                 }
  145.             }
  146.             /* Print an error report if necessary */
  147.             if(!success)
  148.                 PrintFault(IoErr(), "Error");
  149.             FreeDosObject(DOS_EXALLCONTROL,eac);
  150.         }
  151.         else
  152.             printf("Error: could not create ExAll control object\n");
  153.         UnLock(lock);
  154.     }
  155.     else
  156.         printf("Error: could not lock directory \"%s\"\n", dir);
  157.     return success;
  158. }
  159.  
  160. int compareNode(const void* a, const void* b)
  161. {
  162.     struct Node** na = (struct Node**)a;
  163.     struct Node** nb = (struct Node**)b;
  164.     int diff = (*na)->ln_Type - (*nb)->ln_Type;
  165.     if(diff)
  166.         return diff;
  167.     else
  168.         return stricmp((*na)->ln_Name, (*nb)->ln_Name);
  169. }
  170.  
  171. void sortList()
  172. {
  173.     if(mycount > 1)
  174.     {
  175.         struct Node** sortarray = malloc(mycount*sizeof(struct Node*));
  176.         if(sortarray)
  177.         {
  178.             /* Copy pointers to the nodes into the array, in order */
  179.             int i = 0;
  180.             struct Node* next = mylist.lh_Head;
  181.             while(next->ln_Succ)
  182.             {
  183.                 sortarray[i++] = next;
  184.                 next = next->ln_Succ;
  185.             }
  186.             /* Sort the array of pointers */
  187.             qsort(sortarray, mycount, sizeof(struct Node*), &compareNode);
  188.             /* Clear the list, then refill it */
  189.             NewList(&mylist);
  190.             for(i=0; i<mycount; i++)
  191.                 AddTail(&mylist, sortarray[i]);
  192.             free(sortarray);
  193.         }
  194.     }
  195. }
  196.  
  197. /* The start of the program */
  198. void main()
  199. {
  200.     /* Open libraries... */
  201.     if(IntuitionBase = OpenLibrary("intuition.library",37))
  202.     {
  203.         if(GadToolsBase = OpenLibrary("gadtools.library",37))
  204.         {
  205.             if(DosBase = OpenLibrary("dos.library",37))
  206.             {
  207.                 /* Now do the real work */
  208.                 NewList(&mylist);
  209.                 if(fillList("sys:"))
  210.                 {
  211.                     sortList();
  212.                     setupWindow();
  213.                 }
  214.                 freeList();
  215.                 CloseLibrary(DosBase);
  216.             }
  217.             else
  218.                 printf("Error: could not open dos.library\n");
  219.             CloseLibrary(GadToolsBase);
  220.         }
  221.         else
  222.             printf("Error: could not open gadtools.library\n");
  223.         CloseLibrary(IntuitionBase);
  224.     }
  225.     else
  226.         printf("Error: could not open intuition.library\n");
  227. }
  228.  
  229. /* Setup the window -- do the GadTools stuff */
  230. void setupWindow()
  231. {
  232.     struct Screen* scr;
  233.     /* We'll copy the visual information for the default public screen */
  234.   /* (usually, this is the Workbench screen) */
  235.     if(scr = LockPubScreen(NULL))
  236.     {
  237.         APTR vinfo;
  238.         /* Get the visual info so GadTools can render the gadgets nicely */
  239.         if(vinfo = GetVisualInfo(scr, TAG_DONE))
  240.         {
  241.             struct Gadget* glist = NULL;
  242.             struct Gadget* listgad;
  243.             if(listgad = CreateContext(&glist))
  244.             {
  245.                 struct NewGadget newgad;
  246.                 /* The offsets of our window borders */
  247.                 int offleft = scr->WBorLeft;
  248.                 int offtop = scr->WBorTop + (scr->Font->ta_YSize + 1);
  249.                 /* Setup our first gadget */
  250.                 newgad.ng_TextAttr         = &topazFont;
  251.                 newgad.ng_VisualInfo     = vinfo;
  252.                 newgad.ng_LeftEdge         = MYGAD_LEFT + offleft;
  253.                 newgad.ng_TopEdge         = MYGAD_TOP + offtop;
  254.                 newgad.ng_Width             = MYGAD_WIDTH;
  255.                 newgad.ng_Height             = MYGAD_HEIGHT;
  256.                 newgad.ng_GadgetText    = MYGAD_TEXT;
  257.                 newgad.ng_GadgetID        = MYGAD_ID;
  258.                 newgad.ng_Flags                = 0;
  259.                 /* Now create it and add it to our list */
  260.                 if(listgad = CreateGadget(LISTVIEW_KIND, listgad, &newgad,
  261.                                                                     GTLV_Labels, &mylist,
  262.                                                                     TAG_DONE))
  263.                     createWindow(glist);
  264.                 else
  265.                     printf("Error: could not create gadget(s)\n");
  266.                 /* Free the gadget */
  267.                 FreeGadgets(glist);
  268.             }
  269.             else
  270.                 printf("Error: could not create GadTools context\n");
  271.             FreeVisualInfo(vinfo);
  272.         }
  273.         else
  274.             printf("Error: could not get visual info\n");
  275.         UnlockPubScreen(NULL, scr);
  276.     }
  277.     else
  278.         printf("Error: could not lock public screen\n");
  279. }
  280.  
  281. /* Actually open the window, in the normal way */
  282. void createWindow(struct Gadget* glist)
  283. {
  284.     struct Window* win;
  285.     /* Open our window */
  286.     if(win = OpenWindowTags(NULL,
  287.                                                     WA_InnerWidth,    MYWIN_WIDTH,
  288.                                                     WA_InnerHeight,    MYWIN_HEIGHT,
  289.                                                     WA_Title,        "Directory List",
  290.                                                     WA_Flags,        WFLG_CLOSEGADGET | WFLG_DRAGBAR,
  291.                                                     WA_IDCMP,        IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | LISTVIEWIDCMP,
  292.                                                     WA_Gadgets,    glist,
  293.                                                     TAG_DONE,        0))
  294.     {
  295.         /* Let GadTools refresh its bits of the window */
  296.         GT_RefreshWindow(win, NULL);
  297.         /* Now handle messages */
  298.         handleIDCMP(win);
  299.         CloseWindow(win);
  300.     }
  301.     else
  302.         printf("Error: could not open window\n");
  303. }
  304.  
  305. /* Our message handling code */
  306. void handleIDCMP(struct Window* win)
  307. {
  308.     int going = TRUE;
  309.     while(going)
  310.     {
  311.         struct IntuiMessage* intuimsg;
  312.         /* Wait for messages to arrive */
  313.         WaitPort(win->UserPort);
  314.         /* Messages have arrived: loop through all of them */
  315.         while(intuimsg = GT_GetIMsg(win->UserPort))
  316.         {
  317.             /* Act on this message... */
  318.             switch(intuimsg->Class)
  319.             {
  320.             case IDCMP_CLOSEWINDOW:
  321.                 going = FALSE;
  322.                 break;
  323.             case IDCMP_REFRESHWINDOW:
  324.                 /* You *MUST* remember to ask for and handle these refresh messages */
  325.                 GT_BeginRefresh(win);
  326.                 GT_EndRefresh(win, TRUE);
  327.                 break;
  328.             }
  329.             /* Reply when finished with message */
  330.             GT_ReplyIMsg(intuimsg);
  331.         }
  332.     }
  333. }
  334.  
  335.